/*
 * @Author: your name
 * @Date: 2021-02-25 17:15:43
 * @LastEditTime: 2021-03-15 14:51:59
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \xgwsp_frontendd:\project\tsx\demo-tsx\src\axios\request\axios.ts
 */
import axios, { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios';
import Qs from 'qs';
import { RequestType, IParams } from './index.type';
import { ImportMeta } from 'type/common.type';
import { AxiosCanceler } from './cancel';
import { error, failure, format } from './error';
import WebStorage from 'utils/cache';
class VAxios implements RequestType {
  public instance: AxiosInstance;
  private CancelToken = axios.CancelToken;

  constructor(config: AxiosRequestConfig) {
    /** 实例化axios */
    this.instance = this.initInstance(config);
    /** 设置拦截器 */
    this.interceptor();
  }

  request(config: IParams) {
    return this.instance.request(config);
  }

  private initInstance(config: IParams) {
    return axios.create(config);
  }

  private interceptor() {
    const axiosCanceler = new AxiosCanceler();

    this.instance.interceptors.request.use(
      (config: IParams) => {
        const c = { ...config };
        axiosCanceler.add(c);
        if (WebStorage.get('token')) {
          c.headers['x-token'] = WebStorage.get('token');
        }
        return c;
      },
      (err: Error) => {
        return Promise.reject(err);
      }
    );

    this.instance.interceptors.response.use(
      (res: AxiosResponse) => {
        res && axiosCanceler.delete(res.config);
        const { data, config, headers } = res;
        if (config.responseType === 'json') {
          return data.success ? Promise.resolve(data.data) : Promise.reject(data);
        }
        return Promise.resolve({ data, headers });
      },
      (err: Error) => {
        return Promise.reject(err);
      }
    );
  }
}

class RequestProxy {
  private axios: RequestType;

  constructor(config: IParams) {
    this.axios = new VAxios(config);
  }

  public apiGet(url: string, params?: any): Promise<AxiosResponse> {
    return this.request({
      method: 'GET',
      url,
      params: format(params),
      paramsSerializer: (p: any) => {
        return Qs.stringify(p);
      },
    });
  }

  public apiPost(data: IParams): Promise<AxiosResponse> {
    return this.request({
      method: 'POST',
      url: data.url,
      data: format(data.data),
      message: data.message,
      loading: data.loading,
    });
  }

  private async request(config: IParams): Promise<AxiosResponse> {
    try {
      const params = {
        responseType: config.responseType ?? 'json',
        headers: {
          'X-Requested-With': 'XMLHttpRequest',
          'Content-Type': config.headers ?? 'application/json',
        },
      };
      const result = await this.axios.request(Object.assign(params, config));
      return result;
    } catch (e) {
      if (e.message !== '取消请求') {
        if (e.returnCode === '0205') {
          failure();
        } else {
          error(e);
        }
      }
      return Promise.reject(e);
    }
  }
}

const http = new RequestProxy({
  baseURL: (import.meta as ImportMeta).VITE_API,
  timeout: 30000,
});
export default http;
